home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DJGPP
/
DJSRC111.ZIP
/
go32
/
extdebug.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-15
|
8KB
|
292 lines
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
#include <string.h>
#include <dos.h>
#include "gotypes.h"
#include "aout.h"
#include "extdebug.h"
#include "dpmi.h"
#include "paging.h"
#include "tss.h"
#include "exphdlr.h"
#include "mswitch.h"
#include "utils.h"
#include "gdt.h"
#include "utils.h"
#include "eventque.h"
extern EventQueue *event_queue;
extern word32 dr[8];
extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
extern DPMImemory DPMImem; /* DPMI arena address from paging.c */
static ExternalDebuggerInfo ext_debug_info;
int using_external_debugger = 0;
static word16 ourDSsel;
static int breakhandle[4],nset; /* for DPMI breakpoints */
#define VCPI_ED 1
void load_external_debugger(char *fn, char *running_fname, char *argv0)
{
FILEHDR eh;
GNU_AOUT gah;
#if VCPI_ED
word32 edb_base;
#endif
int fd;
char fn2[100], *fns;
fd = _open(fn, O_RDONLY);
if (fd < 0)
{
char *cp;
strcpy(fn2, argv0);
fns = 0;
for (cp=fn2; *cp; cp++)
if (strchr(":\\/", *cp))
fns = cp;
if (fns)
{
strcpy(fns+1, fn);
fd = _open(fn2, O_RDONLY);
if (fd >= 0)
fn = fn2;
}
}
if (fd < 0)
{
char *path = getenv("PATH");
char *pathbeg=path, *pathsep;
while (1)
{
pathsep = pathbeg;
while (*pathsep && *pathsep != ';')
pathsep++;
strncpy(fn2, pathbeg, pathsep-pathbeg);
fn2[pathsep-pathbeg] = '/';
strcpy(fn2+(pathsep-pathbeg)+1, fn);
fd = _open(fn2, O_RDONLY);
if (fd >= 0)
{
fn = fn2;
break;
}
if (*pathsep == 0)
break;
pathbeg = pathsep+1;
}
}
if (fd < 0)
{
fprintf(stderr, "Error: cannot open external debugger file %s\n", fn);
perror("The error was");
exit(1);
}
read(fd, &eh, sizeof(eh));
if (eh.f_magic != 0x14c)
{
fprintf(stderr, "Invalid external debugger %s - not COFF binary\n", fn);
exit(1);
}
read(fd, &gah, sizeof(gah));
#if VCPI_ED
if (use_DPMI)
edb_base = 0;
else
edb_base = 0x90000000L;
if (gah.entry != edb_base+0x0a8L)
{
fprintf(stderr, "Invalid external debugger %s - entry point not 0x%lx (is 0x%lx)\n", fn, edb_base+0xa8L, gah.entry);
if (gah.entry == 0x900000a8L)
fprintf(stderr, "Try using the DPMI binary - ed32-dpmi - instead\n");
if (gah.entry == 0xa8)
fprintf(stderr, "Try using the non-DPMI binary - edebug32 - instead\n");
exit(1);
}
#endif
memcpy(&ed_tss, &a_tss, sizeof(TSS)); /* clone a_tss */
tss_ptr = &ed_tss;
ed_tss.tss_eip = gah.entry;
if (use_DPMI) {
AREAS dbgarea;
word32 newbytes;
DPMImemory dbgmem;
int dbgselect;
dbgarea.first_addr = 0;
dbgarea.last_addr = gah.tsize + gah.dsize + 0xa7;
dbgarea.foffset = 0;
dbgarea.fileno = fd;
newbytes = (dbgarea.last_addr + 0x100fffL) & ~0xfff; /* 1Mb extra */
DPMIprotectedMode();
if (! DPMIalloc(&dbgmem, newbytes)) {
DPMIrealMode();
fprintf(stderr,"DPMI: Not enough memory for debugger (0x%08lx bytes).\n", newbytes);
exit(1);
}
ourDSsel = _DS; /* in protected mode, of course */
dbgselect = DPMIselector(2); /* one for CS, one for SS/DS */
DPMIassignSelector(dbgselect, 0xc0b3, dbgmem.address, dbgmem.bytes - 1 );
DPMIassignSelector(dbgselect+8, 0xc0bb, dbgmem.address, dbgmem.bytes - 1 );
DPMIrealMode();
ed_tss.tss_ds = ed_tss.tss_es = ed_tss.tss_fs =
ed_tss.tss_ss = dbgselect;
ed_tss.tss_cs = dbgselect + 8;
ed_tss.tss_esp = dbgmem.bytes - 12;
ed_tss.tss_eflags = 0x0202;
loadAout(&dbgarea);
Pmemset(dbgselect, dbgarea.last_addr+1, 0, dbgmem.bytes-dbgarea.last_addr-1);
close(fd);
} else {
#if VCPI_ED
areas[A_syms].first_addr = 0xa0000000L;
areas[A_syms].last_addr = 0xa00000a7L + gah.tsize + gah.dsize;
#else
areas[A_syms].first_addr = 0xa0001000L;
areas[A_syms].last_addr = 0xa00010a7L + gah.tsize + gah.dsize;
#endif
areas[A_syms].foffset = 0;
areas[A_syms].fileno = fd;
areas[A_syms2].first_addr = areas[A_syms].last_addr+1;
areas[A_syms2].last_addr = 0xafffffffL;
areas[A_syms2].foffset = -1;
#if !VCPI_ED
ed_tss.tss_esp = 0x0ffffff4l;
ed_tss.tss_ds = g_edds * 8;
ed_tss.tss_es = g_edds * 8;
ed_tss.tss_ss = g_edds * 8;
ed_tss.tss_cs = g_edcs * 8;
ed_tss.tss_edi = 0;
ed_tss.tss_ebx = 0;
ed_tss.tss_ebp = 0;
#else
ed_tss.tss_esp = 0x9ffffff4l;
#endif
ourDSsel = g_rdata * 8;
}
ext_debug_info.version = EXTERNAL_DEBUGGER_VERSION;
ext_debug_info.a_tss_ofs = FP_OFF(&a_tss);
ext_debug_info.a_tss_seg = ourDSsel;
ext_debug_info.filename_ofs = FP_OFF(running_fname);
ext_debug_info.filename_seg = ourDSsel;
ext_debug_info.filename_len = strlen(running_fname);
ext_debug_info.areas_ofs = FP_OFF(&areas);
ext_debug_info.areas_seg = ourDSsel;
ext_debug_info.app_base = ARENA;
ext_debug_info.ansi_mode = use_ansi;
memset(ext_debug_info.dr, 32, 0);
using_external_debugger = 1;
}
void set_break_DPMI(void)
{
int i,enabled,extract;
word16 sizetype;
word32 br_addr;
enabled = (int)dr[7];
extract = (int)(dr[7] >> 16);
nset = 0;
for(i=0;i<4;i++)
if( (enabled >> (i*2))&3 ) {
sizetype = (extract >> (i*4)) & 3; /* extract the type */
if(sizetype == 3) sizetype = 2; /* convert for DPMI brain damage */
sizetype = (sizetype << 8) + ((extract >> (i*4+2)) & 3) + 1; /* & size */
br_addr = dr[i] + DPMImem.address;
breakhandle[i] = DPMIsetBreak(sizetype, br_addr);
if(breakhandle[i] == -1)
fprintf(stderr,"Error allocating DPMI breakpoint at address 0x%08lx\n",dr[i]);
else
nset++;
} else
breakhandle[i] = -1;
return;
}
void clear_break_DPMI(void)
{
int i,bt;
if(!nset) {
dr[6] = 0L;
return;
}
bt = 0;
for(i=3;i>=0;i--) {
bt = bt << 1; /* Shift for next bit */
if(breakhandle[i] != -1)
bt |= DPMIcancelBreak(breakhandle[i]); /* Set low bit if active */
}
dr[6] = (word32)bt;
}
int external_debugger_handler(void)
{
static unsigned char old_enable;
if (tss_ptr != &ed_tss)
return 1;
switch ((word8)(tss_ptr->tss_eax))
{
case EXTERNAL_DEBUGGER_EXECUTE:
if(event_queue != NULL) /* enable events */
event_queue->evq_enable = old_enable;
tss_ptr = &a_tss;
memcpy(dr, ext_debug_info.dr, 32);
if (use_DPMI)
set_break_DPMI();
go_til_stop();
if (use_DPMI)
clear_break_DPMI();
memcpy(ext_debug_info.dr, dr, 32);
if(event_queue != NULL) { /* disable events */
old_enable = event_queue->evq_enable;
event_queue->evq_enable = 0;
}
if (a_tss.tss_irqn <= hard_master_hi && a_tss.tss_irqn >= hard_master_lo)
a_tss.tss_irqn -= hard_master_lo - 8;
if (a_tss.tss_irqn <= hard_slave_hi && a_tss.tss_irqn >= hard_slave_lo)
a_tss.tss_irqn -= hard_slave_lo - 0x70;
tss_ptr = &ed_tss;
return 0;
case EXTERNAL_DEBUGGER_GETINFOPTR:
tss_ptr->tss_eax = FP_OFF(&ext_debug_info);
tss_ptr->tss_edx = ourDSsel;
return 0;
default:
return 1;
}
}